# ImageCacheInotifyHandler - Update cache according to file system changes.
# Copyright (C) 2007 Lauri Taimila
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2007, Lauri Taimila"
__author__ = "Lauri Taimila <lauri@taimila.com>"

import os
import fnmatch
from pyinotify import ProcessEvent

from backend.components.mediacache.image_cache import ImageCache

class ImageCacheInotifyHandler(ProcessEvent):
    """
    Update cache according to file system changes.'
    
    Object from this class handles inotify events for image cache.
    
    NOTE: ImageCache object is created in every method, because SQLite
          doesn't allow cursor to be used in separate threads.
    """
    
    def __init__(self,logger, configuration, fs_observer):
        """
        Create a new ImageCacheInotifyHandler object, which handles file system
        changes. In other words, object from this class makes sure that cache is
        always up-to-date.
        @param logger: Logger object
        @param configuration: Configuration object
        @param fs_observer: FileSystemObserver object
        """
        self.logger = logger
        self.configuration = configuration
        self.fs_observer = fs_observer

    def process_IN_DELETE(self, event):
        """
        File or directory deleted. We are interested in three kinds of events:
        image files, info files and directories.
        """
        print '%s: IN_DELETE' % os.path.join(event.path, event.name) #FIXME: REMOVE THIS DEGUB
        
        image_cache = ImageCache(self.logger, self.configuration)
        
        # Remove directory from cache
        if image_cache.isDirectoryInCache(os.path.join(event.path, event.name)):
            image_cache.removeDirectory(os.path.join(event.path, event.name))
            self.fs_observer.removeFolder(os.path.join(event.path, event.name))
        
        # Album's metadata has been deleted -> Update album
        elif event.name == ".entertainer_album.info" or event.name ==  ".entertainer_album.jpg":
            image_cache.updateDirectory(event.path)
        
        # Remove image file
        elif event.name[event.name.rfind('.')+1 :].lower() == "jpg" or event.name[event.name.rfind('.')+1 :].lower() == "jpeg":
            image_cache.removeFile(os.path.join(event.path, event.name))
        
        # Metadata information file has been removed. Update image in cache    
        elif fnmatch.fnmatch(event.name, ".*.info"):
            jpg = event.name[1:event.name.rfind('.')] + ".jpg"
            if os.path.exists(os.path.join(event.path, jpg)):
                image_cache.updateFile(os.path.join(event.path, jpg))
                return
            jpeg = event.name[1:event.name.rfind('.')] + ".jpeg"
            if os.path.exists(os.path.join(event.path, jpeg)):
                image_cache.updateFile(os.path.join(event.path, jpeg))
                
    def process_IN_CREATE(self, event):
        """
        File or directory created. We are interested in three kinds of events:
        image files, info files and directories.
        """
        print '%s: IN_CREATE' % os.path.join(event.path, event.name) #FIXME: REMOVE THIS DEGUB
        
        image_cache = ImageCache(self.logger, self.configuration)
        
        # Create album to image cache (is this useless?) Can there be images in dir when IN_CREATE occurs
        if os.path.isdir(os.path.join(event.path, event.name)): 
            self.fs_observer.addFolder(os.path.join(event.path, event.name), "image")
            image_cache.addDirectory(os.path.join(event.path, event.name))
            
        # Album's metadata has been created -> Update album
        elif event.name == ".entertainer_album.info" or event.name ==  ".entertainer_album.jpg":
            image_cache.updateDirectory(event.path)
            
        # Add image to the cache
        elif event.name[event.name.rfind('.')+1 :].lower() == "jpg" or event.name[event.name.rfind('.')+1 :].lower() == "jpeg":
            image_cache.addFile(os.path.join(event.path, event.name))
            
        # Info file created -> Update image in cache if exists
        elif fnmatch.fnmatch(event.name, ".*.info"):
            jpg = event.name[1:event.name.rfind('.')] + ".jpg"
            if os.path.exists(os.path.join(event.path, jpg)):
                image_cache.updateFile(os.path.join(event.path, jpg))
                return
            jpeg = event.name[1:event.name.rfind('.')] + ".jpeg"
            if os.path.exists(os.path.join(event.path, jpeg)):
                image_cache.updateFile(os.path.join(event.path, jpeg))
            
    def process_IN_DELETE_SELF(self, event):
        """
        Listened root directory was deleted. One of the directories that is 
        listed in content.conf
        """
        print '%s: IN_DELETE_SELF' % os.path.join(event.path, event.name) #FIXME: REMOVE THIS DEGUB
        image_cache = ImageCache(self.logger, self.configuration)
        if image_cache.isDirectoryInCache(os.path.join(event.path, event.name)):
            image_cache.removeDirectory(os.path.join(event.path, event.name))
            self.fs_observer.removeFolder(os.path.join(event.path, event.name))
        
    def process_IN_MODIFY(self, event):
        """
        File or directory was modified. We are interested in three kinds of events:
        image files, info files and directories.
        """
        print '%s: IN_MODIFY' % os.path.join(event.path, event.name) #FIXME: REMOVE THIS DEGUB
        
        image_cache = ImageCache(self.logger, self.configuration)
        
        # Directory was modified
        # FIXME: DO WE NEED THIS AT ALL?
        if os.path.isdir(os.path.join(event.path, event.name)):
            image_cache.updateDirectory(os.path.join(event.path, event.name))
        
        # Album's metadata has been modified -> Update album
        elif event.name == ".entertainer_album.info" or event.name ==  ".entertainer_album.jpg":
            image_cache.updateDirectory(event.path)
        
        # Image file was modified    
        elif event.name[event.name.rfind('.')+1 :].lower() == "jpg" or event.name[event.name.rfind('.')+1 :].lower() == "jpeg":
            image_cache.updateFile(os.path.join(event.path, event.name))
         
        # Metadata file was modified    
        elif fnmatch.fnmatch(event.name, ".*.info"):
            jpg = event.name[1:event.name.rfind('.')] + ".jpg"
            if os.path.exists(os.path.join(event.path, jpg)):
                image_cache.updateFile(os.path.join(event.path, jpg))
                return
            jpeg = event.name[1:event.name.rfind('.')] + ".jpeg"
            if os.path.exists(os.path.join(event.path, jpeg)):
                image_cache.updateFile(os.path.join(event.path, jpeg))
                
    def process_IN_MOVED_FROM(self, event):
        """
        File is moved away
        """
        print '%s: IN_MOVED_FROM' % os.path.join(event.path, event.name) #FIXME: REMOVE THIS DEGUB
        
        image_cache = ImageCache(self.logger, self.configuration)
        
        # Directory moved away -> remove from cache
        if image_cache.isDirectoryInCache(os.path.join(event.path, event.name)):
            print "MOVED IS A DIRECTORY" # FIXME: Remove this debug line
            image_cache.removeDirectory(os.path.join(event.path, event.name))
            self.fs_observer.removeFolder(os.path.join(event.path, event.name))
        
        # Album's metadata has been moved away -> Update album
        elif event.name == ".entertainer_album.info" or event.name ==  ".entertainer_album.jpg":
             image_cache.updateDirectory(event.path)
        
        # Image file moved away    
        elif event.name[event.name.rfind('.')+1 :].lower() == "jpg" or event.name[event.name.rfind('.')+1 :].lower() == "jpeg":
            image_cache.removeFile(os.path.join(event.path, event.name))
            
        # Metadata file moved away
        elif fnmatch.fnmatch(event.name, ".*.info"):
            jpg = event.name[1:event.name.rfind('.')] + ".jpg"
            if os.path.exists(os.path.join(event.path, jpg)):
                image_cache.updateFile(os.path.join(event.path, jpg))
                return
            jpeg = event.name[1:event.name.rfind('.')] + ".jpeg"
            if os.path.exists(os.path.join(event.path, jpeg)):
                image_cache.updateFile(os.path.join(event.path, jpeg))
    
    def process_IN_MOVED_TO(self, event):
        """
        File is moved to (from somewhere or renamed)
        """
        print '%s: IN_MOVED_TO' % os.path.join(event.path, event.name) #FIXME: REMOVE THIS DEGUB
        
        image_cache = ImageCache(self.logger, self.configuration)
        
        # Directory moved to observed directory hierarcy
        if os.path.isdir(os.path.join(event.path, event.name)):
            image_cache.addDirectory(os.path.join(event.path, event.name))
            self.fs_observer.addFolder(os.path.join(event.path, event.name), "image")
        
        # Album's metadata has been moved in -> Update album
        elif event.name == ".entertainer_album.info" or event.name ==  ".entertainer_album.jpg":
            image_cache.updateDirectory(event.path)
            
        # Image file moved to observed directory hierarcy
        elif event.name[event.name.rfind('.')+1 :].lower() == "jpg" or event.name[event.name.rfind('.')+1 :].lower() == "jpeg":
            image_cache.addFile(os.path.join(event.path, event.name))
            
        # Metadata file moved to observed directory hierarcy
        elif fnmatch.fnmatch(event.name, ".*.info"):
            jpg = event.name[1:event.name.rfind('.')] + ".jpg"
            if os.path.exists(os.path.join(event.path, jpg)):
                image_cache.updateFile(os.path.join(event.path, jpg))
                return
            jpeg = event.name[1:event.name.rfind('.')] + ".jpeg"
            if os.path.exists(os.path.join(event.path, jpeg)):
                image_cache.updateFile(os.path.join(event.path, jpeg))
        
    def process_IN_MOVE_SELF(self, event):
        """
        Observed folder has been moved.
        """
        print '%s: IN_MOVE_SELF' % os.path.join(event.path, event.name) #FIXME: REMOVE THIS DEGUB
        #FIXME: WHAT SHOULD BE DONE HERE?!!
        
    def process_default(self, event):
        """
        Ultimately, this method is called for all others kind of events.
        """
        pass
